package com.xiaozhen.data.config;

import com.xiaozhen.data.utils.DateUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.influxdb.InfluxDB;
import org.influxdb.InfluxDBFactory;
import org.influxdb.dto.BatchPoints;
import org.influxdb.dto.Point;
import org.influxdb.dto.Point.Builder;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zhenweisheng
 * @date 2020/9/30 8:52
 * @description:
 */
@Data
@Slf4j
public class InfluxDBConnect {
    /**
     * 用户名
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 连接地址
     */
    private String openurl;
    /**
     * 数据库
     */
    private String database;
    private InfluxDB influxDB;

    public InfluxDBConnect(String username, String password, String openurl, String database) {
        this.username = username;
        this.password = password;
        this.openurl = openurl;
        this.database = database;
    }

    /**
     * 连接时序数据库；获得InfluxDB
     **/
    public InfluxDB influxDbBuild() {
        log.info("------------------------:{},-------{},{},----{}", username, password, openurl, database);
        if (influxDB == null) {
            influxDB = InfluxDBFactory.connect(openurl, username, password);
            influxDB.createDatabase(database);
        }
        return influxDB;
    }

    /**
     * 设置数据保存策略 defalut 策略名 /database 数据库名/ 30d 数据保存时限30天/ 1 副本个数为1/ 结尾DEFAULT
     * 表示 设为默认的策略
     */
    public void createRetentionPolicy(String days) {
        String command = String.format("CREATE RETENTION POLICY \"%s\" ON \"%s\" DURATION %s REPLICATION %s DEFAULT",
                "defalut", database, days, 1);
        this.query(command);
    }

    /**
     * 查询
     *
     * @param command 查询语句
     * @return
     */
    public QueryResult query(String command) {
        return influxDB.query(new Query(command, database));
    }

    /**
     * 单一 插入
     *
     * @param measurement 表
     * @param tags        标签
     * @param fields      字段
     */
    public void insert(String measurement, Map<String, String> tags, Map<String, Object> fields) {
        Builder builder = Point.measurement(measurement);
        if (fields.get("currentTime") != null) {
            builder.time((long) fields.get("currentTime"), TimeUnit.MICROSECONDS);
            fields.remove("currentTime");
        } else {
            builder.time(DateUtil.getMicTime(), TimeUnit.MICROSECONDS);
        }
        builder.tag(tags);
        builder.fields(fields);

        influxDB.write(database, "", builder.build());
    }

    /**
     * 批量插入
     *
     * @param measurement 表
     * @param tags        标签
     * @param fieldsList  字段
     */
    public void batchInsert(String measurement, Map<String, String> tags, List<Map<String, Object>> fieldsList) {
        org.influxdb.dto.BatchPoints.Builder batchbuilder = BatchPoints.database(database);

        for (Map<String, Object> map : fieldsList) {
            Builder builder = Point.measurement(measurement);
            if (map.get("currentTime") != null) {
                builder.time((long) map.get("currentTime"), TimeUnit.MICROSECONDS);
                map.remove("currentTime");
            } else {
                builder.time(DateUtil.getMicTime(), TimeUnit.MICROSECONDS);
            }
            builder.tag(tags);
            builder.fields(map);
            batchbuilder.point(builder.build());
        }

        System.out.println(batchbuilder.build().toString());

        influxDB.write(batchbuilder.build());
    }

    /**
     * 删除
     *
     * @param command 删除语句
     * @return 返回错误信息
     */
    public String deleteMeasurementData(String command) {
        QueryResult result = influxDB.query(new Query(command, database));
        return result.getError();
    }

    /**
     * 创建数据库
     *
     * @param dbName
     */
    public void createDB(String dbName) {
        influxDB.createDatabase(dbName);
    }

    /**
     * 删除数据库
     *
     * @param dbName
     */
    public void deleteDB(String dbName) {
        influxDB.deleteDatabase(dbName);
    }

}

